//===============================================================================
// Microsoft Architecture Strategy Team
// LitwareHR - SaaS Sample Application
//===============================================================================
// Copyright  Microsoft Corporation.  All rights reserved.
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY
// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT
// LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE.
//===============================================================================
// The example companies, organizations, products, domain names,
// e-mail addresses, logos, people, places, and events depicted
// herein are fictitious.  No association with any real company,
// organization, product, domain name, email address, logo, person,
// places, or events is intended or should be inferred.
//===============================================================================


using System;
using System.Data;
using System.Configuration;
using System.Linq;
using System.Xml.Linq;
using System.Net;
using System.IO;
using System.Globalization;
using System.Web;
using System.Xml;


namespace LitwareHR.Recruiting.Services
{

    /// <summary>
    /// Summary description for SlsHelper
    /// </summary>
    public sealed class SlsHelper
    {
        private SlsHelper()
        {
        }

        private const string baseSLSUrl = "http://silverlight.services.live.com/{0}/{1}";
        private const string slsTemplateApplicationPath = "SlsTemplateApplicationPath";
        private const string slsTempWorkingPath = "SlsTempWorkingPath";
        private const string destinationTemplateTempFolderName = @"SilverlightTemp_{0}";
        private const string zipFileName = @"SilverlightFileSet_{0}.zip";
        private const string relativeMediaFilePath = @"media\mediaFile.wmv";
        private const string xamlPlayerName = @"player.xaml";
        private const string waterMarkXpath = @"//*[local-name()='TextBlock' and namespace-uri()='http://schemas.microsoft.com/winfx/2006/xaml/presentation'][@Canvas.ZIndex='5']";

        private const long BUFFER_SIZE = 8192;        

        internal static string SourceTemplateApplicationPath
        {
            get
            {
                return ConfigurationManager.AppSettings[slsTemplateApplicationPath];
            }
        }

        internal static string DestinationTempWorkingPath
        {
            get
            {
                return ConfigurationManager.AppSettings[slsTempWorkingPath];
            }
        }       


        public static bool UploadFileSet(string accountId, string accountKey, byte[] value, string fileSetName, string tenantAlias)
        {
            if (value == null) throw new ArgumentNullException("value");
            if (String.IsNullOrEmpty(fileSetName)) throw new ArgumentNullException("fileSetName");

            Guid instanceId = Guid.NewGuid();
            string instanceDestinationTemplateFolder = Path.Combine(DestinationTempWorkingPath, String.Format(CultureInfo.InvariantCulture, destinationTemplateTempFolderName, instanceId));
            string instanceZipFilePath = Path.Combine(DestinationTempWorkingPath, String.Format(CultureInfo.InvariantCulture, zipFileName, instanceId));

            //create temp application
            CopyApplicationTemplate(SourceTemplateApplicationPath, instanceDestinationTemplateFolder);

            //set watermark text
            SetWaterMark(Path.Combine(instanceDestinationTemplateFolder, xamlPlayerName), tenantAlias);

            //add video file
            FileHelper.CreateFileFromByteArray(value, Path.Combine(instanceDestinationTemplateFolder, relativeMediaFilePath));

            //compress
            ZipHelper.Compress(instanceDestinationTemplateFolder, instanceZipFilePath);

            //submit application
            bool result = SubmitSilverlightApplication(accountId, accountKey, fileSetName, instanceZipFilePath);

            //Delete temp folder
            FileHelper.DeleteDirectory(instanceDestinationTemplateFolder);

            //Delete temp zip
            File.Delete(instanceZipFilePath);

            return result;
        }

        private static bool SubmitSilverlightApplication(string accountId, string accountKey, string fileSetName, string fileSetPath)
        {    
            HttpWebRequest req = GetRESTHttpWebRequest(accountId, accountKey, fileSetName);

            using (FileStream inputStream = new FileStream(fileSetPath, FileMode.Open, FileAccess.Read))
            {
                using (Stream requestStream = req.GetRequestStream())
                {
                    CopyStream(inputStream, requestStream);
                    requestStream.Close();
                }
            }

            HttpWebResponse resp = (HttpWebResponse)req.GetResponse();

            return resp.StatusCode == HttpStatusCode.OK;
        }

        private static HttpWebRequest GetRESTHttpWebRequest(string accountId, string accountKey, string fileSetName)
        {
            //serviceRoot/accountId/fileSetName
            Uri requestAccountUriString = new Uri(String.Format(CultureInfo.InvariantCulture, baseSLSUrl, accountId, fileSetName));
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(requestAccountUriString);
            request.Method = WebRequestMethods.Http.Post;
            request.PreAuthenticate = true;
            request.ContentType = System.Net.Mime.MediaTypeNames.Application.Zip;
            request.Timeout = 900000;
            request.ReadWriteTimeout = 1200000;

            //Note: When setting the authorization header with NetworkCredential, uploading large files will timeout
            byte[] userPass = System.Text.Encoding.Default.GetBytes(accountId + ":" + accountKey);
            string basic = "Basic " + Convert.ToBase64String(userPass);
            request.Headers["Authorization"] = basic;

            return request;
        }

        private static void CopyStream(FileStream inputStream, Stream requestStream)
        {
            long bufferSize = inputStream.Length < BUFFER_SIZE ? inputStream.Length : BUFFER_SIZE;
            byte[] buffer = new byte[bufferSize];
            int bytesRead = 0;
            long bytesWritten = 0;
            while ((bytesRead = inputStream.Read(buffer, 0, buffer.Length)) != 0)
            {
                requestStream.Write(buffer, 0, bytesRead);
                bytesWritten += bufferSize;
            }
        }

        private static void CopyApplicationTemplate(string sourcePath, string destinationPath )
        {
            FileHelper.DeleteDirectory(destinationPath);
            Directory.CreateDirectory(destinationPath);
            FileHelper.CopyFolder(sourcePath, destinationPath);
        }

        private static void SetWaterMark(string sourcePath, string text)
        {
            XmlDocument xmlDoc = new XmlDocument();
            xmlDoc.Load(sourcePath);

            XmlNode node = xmlDoc.SelectSingleNode(waterMarkXpath);

            if (node != null)
            {
                node.InnerXml = text;
            }

            xmlDoc.Save(sourcePath);
        }     
    }
}
